﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<ctype.h>
#include<assert.h>

//为什么使⽤⽂件
//如果没有⽂件，我们写的程序的数据是存储在电脑的内存中，如果程序退出，内存回收，数据就丢失了。
// 等再次运⾏程序，是看不到上次程序的数据的，如果要将数据进⾏持久化的保存，我们可以使⽤⽂件
//什么是⽂件？
//磁盘（硬盘）上的⽂件是⽂件。
//但是在程序设计中，我们⼀般谈的⽂件有两种：程序⽂件、数据⽂件（从⽂件功能的⻆度来分类的）。
//程序⽂件
//程序⽂件包括源程序⽂件（后缀为.c）, ⽬标⽂件（windows环境后缀为.obj）, 可执⾏程序（windows环境后缀为.exe）。
//数据⽂件
//⽂件的内容不⼀定是程序，⽽是程序运⾏时读写的数据，⽐如程序运⾏需要从中读取数据的⽂件，或者输出内容的⽂件。
//本章讨论的是数据⽂件。
//在以前各章所处理数据的输⼊输出都是以终端为对象的，即从终端的键盘输⼊数据，运⾏结果显⽰到显⽰器上。
//其实有时候我们会把信息输出到磁盘上，当需要的时候再从磁盘上把数据读取到内存中使⽤，这⾥处理的就是磁盘上⽂件。
//⽂件名
//⼀个⽂件要有⼀个唯⼀的⽂件标识，以便⽤⼾识别和引⽤。
//⽂件名包含3部分：⽂件路径 + ⽂件名主⼲ + ⽂件后缀
//例如： c : \code\test.txt
//为了⽅便起⻅，⽂件标识常被称为⽂件名。
//⼆进制⽂件和⽂本⽂件？
//根据数据的组织形式，数据⽂件被称为⽂本⽂件或者⼆进制⽂件。
//数据在内存中以⼆进制的形式存储，如果不加转换的输出到外存的⽂件中，就是⼆进制⽂件。
//如果要求在外存上以ASCII码的形式存储，则需要在存储前转换。以ASCII字符的形式存储的⽂件就是⽂本⽂件。
//⼀个数据在⽂件中是怎么存储的呢？
//字符⼀律以ASCII形式存储，数值型数据既可以⽤ASCII形式存储，也可以使⽤⼆进制形式存储。
//如有整数10000，如果以ASCII码的形式输出到磁盘，则磁盘中占⽤5个字节（每个字符⼀个字节），⽽
//⼆进制形式输出，则在磁盘上只占4个字节（VS2019测试）
// 
//int main()
//{
//	int a = 10000;
//	FILE* pf = fopen("test.txt", "wb");
//	fwrite(&a, 4, 1, pf);//⼆进制的形式写到⽂件中 
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//⽂件的打开和关闭
//流和标准流
//流
//我们程序的数据需要输出到各种外部设备，也需要从外部设备获取数据，不同的外部设备的输⼊输出
//操作各不相同，为了⽅便程序员对各种设备进⾏⽅便的操作，我们抽象出了流的概念，我们可以把流想象成流淌着字符的河。
//C程序针对⽂件、画⾯、键盘等的数据输⼊输出操作都是通过流操作的。
//⼀般情况下，我们要想向流⾥写数据，或者从流中读取数据，都是要打开流，然后操作。
//标准流
//那为什么我们从键盘输⼊数据，向屏幕上输出数据，并没有打开流呢？
//那是因为C语⾔程序在启动的时候，默认打开了3个流：
//• stdin- 标准输⼊流，在⼤多数的环境中从键盘输⼊，scanf函数就是从标准输⼊流中读取数据。
//• stdout-标准输出流，⼤多数的环境中输出⾄显⽰器界⾯，printf函数就是将信息输出到标准输出流中。
//• stderr-标准错误流，⼤多数环境中输出到显⽰器界⾯。
//这是默认打开了这三个流，我们使⽤scanf、printf等函数就可以直接进⾏输⼊输出操作的。
//stdin、stdout、stderr三个流的类型是： FILE * ，通常称为⽂件指针。
//C语⾔中，就是通过 FILE * 的⽂件指针来维护流的各种操作的。

//⽂件指针
//缓冲⽂件系统中，关键的概念是“⽂件类型指针”，简称“⽂件指针”。
//每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区，⽤来存放⽂件的相关信息（如⽂件的名字，⽂件状态及⽂件当前的位置等）。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的，取名FILE.
//例如，VS2013编译环境提供的 stdio.h 头⽂件中有以下的⽂件类型申明：

//struct _iobuf {
//	char* _ptr;
//	int _cnt;
//	char* _base;
//	int _flag;
//	int _file;
//	int _charbuf;
//	int _bufsiz;
//	char* _tmpfname;
//};
//typedef struct _iobuf FILE; struct _iobuf {
//	char* _ptr;
//	int _cnt;
//	char* _base;
//	int _flag;
//	int _file;
//	int _charbuf;
//	int _bufsiz;
//	char* _tmpfname;
//};
//typedef struct _iobuf FILE;

//不同的C编译器的FILE类型包含的内容不完全相同，但是⼤同⼩异。
//每当打开⼀个⽂件的时候，系统会根据⽂件的情况⾃动创建⼀个FILE结构的变量，并填充其中的信息，使⽤者不必关⼼细节。
//⼀般都是通过⼀个FILE的指针来维护这个FILE结构的变量，这样使⽤起来更加⽅便。
//下⾯我们可以创建⼀个FILE* 的指针变量:
//FILE* pf;//⽂件指针变量
//定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个⽂件的⽂件信息区（是⼀个结构体变量）。
// 通过该⽂件信息区中的信息就能够访问该⽂件。也就是说，通过⽂件指针变量能够间接找到与它关联的⽂件

//⽂件的打开和关闭
//⽂件在读写之前应该先打开⽂件，在使⽤结束之后应该关闭⽂件。
//在编写程序的时候，在打开⽂件的同时，都会返回⼀个FILE* 的指针变量指向该⽂件，也相当于建⽴了指针和⽂件的关系。
//ANSIC规定使⽤ fopen 函数来打开⽂件， fclose 来关闭⽂件。

//打开⽂件 
//FILE* fopen(const char* filename, const char* mode);
//关闭⽂件 
//int fclose(FILE* stream);

///* fopen fclose example */
//#include <stdio.h>
//int main()
//{
//	FILE* pFile;
//	//打开⽂件 
//	pFile = fopen("myfile.txt", "w");
//	//⽂件操作 
//	if (pFile != NULL)
//	{
//		fputs("fopen example", pFile);
//		//关闭⽂件 
//		fclose(pFile);
//	}
//	return 0;
//}

//⽂件的随机读写
//int main()
//{
//	//打开文件
//	FILE* pf= fopen("test.txt", 'w');
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//写文件
//	char ch = 0;
//	for (ch = 'a'; ch < 'z'; ch++)
//	{
//		fputc(ch, pf);
//	}
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}

//int main()
//{
//	//打开文件
//	FILE* pf = fopen("test.txt", 'w');
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	int ch = 0;
//	 while ((ch = fgetc(pf) != EOF))
//	{
//		 printf("%c", ch);
//	}
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}


//int main()
//{
//	//打开文件
//	FILE* pf = fopen("test.txt", 'w');
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//写文件
//	fputs("hellow world\n", pf);
//	fputs("hellow bit", pf);
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}



//int main()
//{
//	//打开文件
//	FILE* pf = fopen("test.txt", 'w');
//	if (pf == NULL)
//	{
//		perror("fopen");
//		return 1;
//	}
//	//读文件
//	char arr[20] = { 0 };
//	while (fgets(arr, 20, pf) != NULL)
//	{
//		printf("%s", arr);
//	}
//	//关闭文件
//	fclose(pf);
//	pf = NULL;
//	return 0;
//}
























